bitkeeper revision 1.1155 (411350f1WPGKHyDE_nv5WX9LJBbaWg)
authorkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Fri, 6 Aug 2004 09:35:45 +0000 (09:35 +0000)
committerkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Fri, 6 Aug 2004 09:35:45 +0000 (09:35 +0000)
Add support for marking bad pages using the 'badpage=xxx'
cmdline option when booting Xen.

README.CD
docs/HOWTOs/Xen-HOWTO
docs/user.tex
xen/common/kernel.c
xen/common/page_alloc.c
xen/include/xen/lib.h

index fcf94be18f9fc11b401025f954d029f8e1c35500..3ea9eb7639ffba74415de642eb508137a7ef777d 100644 (file)
--- a/README.CD
+++ b/README.CD
@@ -277,6 +277,13 @@ that may be able to help diagnose problems:
 
  noht            Disable Hyperthreading.
 
+ badpage=<page number>[,<page number>]*
+                  Specify a list of pages not to be allocated for use 
+                  because they contain bad bytes. For example, if your
+                  memory tester says that byte 0x12345678 is bad, you would
+                  place 'badpage=0x12345' on Xen's command line (i.e., the
+                  last three digits of the byte address are not included!).
+
  com1=<baud>,DPS[,<io_base>,<irq>]
  com2=<baud>,DPS[,<io_base>,<irq>]
                   Xen supports up to two 16550-compatible serial ports.
index 272670baa1680f7f8d0012856304fcc0fb629a66..62cbfc68885b1eb31912662a9f00a31dad4d1458 100644 (file)
@@ -223,6 +223,13 @@ The following is a list of command line arguments to pass to Xen:
 
  noht             Disable Hyperthreading.
 
+ badpage=<page number>[,<page number>]*
+                  Specify a list of pages not to be allocated for use 
+                  because they contain bad bytes. For example, if your
+                  memory tester says that byte 0x12345678 is bad, you would
+                  place 'badpage=0x12345' on Xen's command line (i.e., the
+                  last three digits of the byte address are not included!).
+
  com1=<baud>,DPS[,<io_base>,<irq>]
  com2=<baud>,DPS[,<io_base>,<irq>]
                   Xen supports up to two 16550-compatible serial ports.
index e13c1a50d03fe0178aa6dea2aafc444881c6f71b..bdb546b85314af07e5ea30aeffcbcb05d8fb5048 100644 (file)
@@ -1140,6 +1140,14 @@ editting \path{grub.conf}.
 {\bf noht } \\
  Disable Hyperthreading. \\
 
+{\bf badpage=$<$page number$>$[,$<$page number$>$] } \\
+                  Specify a list of pages not to be allocated for use 
+                  because they contain bad bytes. For example, if your
+                  memory tester says that byte 0x12345678 is bad, you would
+                  place 'badpage=0x12345' on Xen's command line (i.e., the
+                  last three digits of the byte address are not
+                  included!). \\
+
 {\bf com1=$<$baud$>$,DPS[,$<$io\_base$>$,$<$irq$>$] \\
  com2=$<$baud$>$,DPS[,$<$io\_base$>$,$<$irq$>$] } \\
  Xen supports up to two 16550-compatible serial ports.
index de9e1c26c9948ec714cc0caca4db7aab939eb9f9..6a39946d700d276f7a6a574c942bd483f0a23b6e 100644 (file)
@@ -91,32 +91,40 @@ char opt_nmi[10] = "dom0";
 #else
 char opt_nmi[10] = "fatal";
 #endif
+/*
+ * Comma-separated list of hexadecimal page numbers containing bad bytes.
+ * e.g. 'badpage=0x3f45,0x8a321'.
+ */
+char opt_badpage[100] = "";
 
 static struct {
     unsigned char *name;
     enum { OPT_STR, OPT_UINT, OPT_BOOL } type;
     void *var;
+    unsigned int len;
 } opts[] = {
-    { "console",           OPT_STR,  &opt_console },
-    { "conswitch",         OPT_STR,  &opt_conswitch },
-    { "com1",              OPT_STR,  &opt_com1 },
-    { "com2",              OPT_STR,  &opt_com2 },
-    { "dom0_mem",          OPT_UINT, &opt_dom0_mem }, 
-    { "noht",              OPT_BOOL, &opt_noht },
-    { "noacpi",            OPT_BOOL, &opt_noacpi },
-    { "nosmp",             OPT_BOOL, &opt_nosmp },
-    { "noreboot",          OPT_BOOL, &opt_noreboot },
-    { "ignorebiostables",  OPT_BOOL, &opt_ignorebiostables },
-    { "watchdog",          OPT_BOOL, &opt_watchdog },
-    { "pdb",               OPT_STR,  &opt_pdb },
-    { "tbuf_size",         OPT_UINT, &opt_tbuf_size },
-    { "sched",             OPT_STR,  &opt_sched },
-    { "physdev_dom0_hide", OPT_STR,  &opt_physdev_dom0_hide },
-    { "leveltrigger",      OPT_STR,  &opt_leveltrigger },
-    { "edgetrigger",       OPT_STR,  &opt_edgetrigger },
-    { "xenheap_megabytes", OPT_UINT, &opt_xenheap_megabytes },
-    { "nmi",               OPT_STR,  &opt_nmi },
-    { NULL,               0,        NULL     }
+#define V(_x) &_x, sizeof(_x)
+    { "console",           OPT_STR,  V(opt_console) },
+    { "conswitch",         OPT_STR,  V(opt_conswitch) },
+    { "com1",              OPT_STR,  V(opt_com1) },
+    { "com2",              OPT_STR,  V(opt_com2) },
+    { "dom0_mem",          OPT_UINT, V(opt_dom0_mem) },
+    { "noht",              OPT_BOOL, V(opt_noht) },
+    { "noacpi",            OPT_BOOL, V(opt_noacpi) },
+    { "nosmp",             OPT_BOOL, V(opt_nosmp) },
+    { "noreboot",          OPT_BOOL, V(opt_noreboot) },
+    { "ignorebiostables",  OPT_BOOL, V(opt_ignorebiostables) },
+    { "watchdog",          OPT_BOOL, V(opt_watchdog) },
+    { "pdb",               OPT_STR,  V(opt_pdb) },
+    { "tbuf_size",         OPT_UINT, V(opt_tbuf_size) },
+    { "sched",             OPT_STR,  V(opt_sched) },
+    { "physdev_dom0_hide", OPT_STR,  V(opt_physdev_dom0_hide) },
+    { "leveltrigger",      OPT_STR,  V(opt_leveltrigger) },
+    { "edgetrigger",       OPT_STR,  V(opt_edgetrigger) },
+    { "xenheap_megabytes", OPT_UINT, V(opt_xenheap_megabytes) },
+    { "nmi",               OPT_STR,  V(opt_nmi) },
+    { "badpage",           OPT_STR,  V(opt_badpage) },
+    { NULL,                0,        NULL, 0 }
 };
 
 
@@ -154,7 +162,10 @@ void cmain(multiboot_info_t *mbi)
                 {
                 case OPT_STR:
                     if ( opt != NULL )
-                        strcpy(opts[i].var, opt);
+                    {
+                        strncpy(opts[i].var, opt, opts[i].len);
+                        ((char *)opts[i].var)[opts[i].len-1] = '\0';
+                    }
                     break;
                 case OPT_UINT:
                     if ( opt != NULL )
index db3a01f4fe7289171a37dcbd7c4175fbb56b6ece..a57d43b9c3cccbe8f9d99e940c3d45aedff0eb1c 100644 (file)
@@ -29,6 +29,7 @@
 #include <xen/slab.h>
 #include <xen/irq.h>
 
+extern char opt_badpage[];
 
 /*********************
  * ALLOCATION BITMAP
@@ -137,7 +138,8 @@ unsigned long init_heap_allocator(
     unsigned long bitmap_start, unsigned long max_pages)
 {
     int i, j;
-    unsigned long bitmap_size;
+    unsigned long bitmap_size, bad_pfn;
+    char *p;
 
     memset(avail, 0, sizeof(avail));
 
@@ -155,40 +157,42 @@ unsigned long init_heap_allocator(
     /* All allocated by default. */
     memset(alloc_bitmap, ~0, bitmap_size);
 
+    /*
+     * Process the bad-page list. Marking the page free in the bitmap will
+     * indicate to init_heap_pages() that it should not be placed on the 
+     * buddy lists.
+     */
+    p = opt_badpage;
+    while ( *p != '\0' )
+    {
+        bad_pfn = simple_strtoul(p, &p, 0);
+
+        if ( *p == ',' )
+            p++;
+        else if ( *p != '\0' )
+            break;
+
+        if ( (bad_pfn < max_pages) && allocated_in_map(bad_pfn) )
+        {
+            printk("Marking page %08lx as bad\n", bad_pfn);
+            map_free(bad_pfn, 1);
+        }
+    }
+
     return bitmap_start + bitmap_size;
 }
 
 /* Hand the specified arbitrary page range to the specified heap zone. */
 void init_heap_pages(int zone, struct pfn_info *pg, unsigned long nr_pages)
 {
-    int i;
-    unsigned long flags;
+    unsigned long i, pfn = page_to_pfn(pg);
 
-    spin_lock_irqsave(&heap_lock, flags);
-
-    /* Free up the memory we've been given to play with. */
-    map_free(page_to_pfn(pg), nr_pages);
-    avail[zone] += nr_pages;
-    
-    while ( nr_pages != 0 )
+    /* Process each page in turn, skipping bad pages. */
+    for ( i = 0; i < nr_pages; i++ )
     {
-        /*
-         * Next chunk is limited by alignment of pg, but also must not be
-         * bigger than remaining bytes.
-         */
-        for ( i = 0; i < MAX_ORDER; i++ )
-            if ( ((page_to_pfn(pg) & (1 << i)) != 0) ||
-                 ((1 << (i + 1)) > nr_pages) )
-                break;
-
-        PFN_ORDER(pg) = i;
-        list_add_tail(&pg->list, &heap[zone][i]);
-
-        pg       += 1 << i;
-        nr_pages -= 1 << i;
+        if ( likely(allocated_in_map(pfn+i)) ) /* bad page? */
+            free_heap_pages(zone, pg+i, 0);
     }
-
-    spin_unlock_irqrestore(&heap_lock, flags);
 }
 
 
index d4899efe6a28976c0811b367bf0de68cc399ce8d..e9893a2f6f08840f22850d6ba0934b476c9568fb 100644 (file)
@@ -6,7 +6,7 @@
 #include <xen/string.h>
 
 #ifndef NDEBUG
-#define ASSERT(_p) if ( !(_p) ) { printk("Assertion '%s' failed, line %d, file %s", #_p , __LINE__, __FILE__); *(int*)0=0; }
+#define ASSERT(_p) if ( !(_p) ) { printk("Assertion '%s' failed, line %d, file %s\n", #_p , __LINE__, __FILE__); *(int*)0=0; }
 #else
 #define ASSERT(_p) ((void)0)
 #endif